﻿using System;
using Styx;
using Styx.Pathing;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using Logger = HolySword.Helpers.LogManager;
using HolySword.Delegates;

namespace HolySword.Helpers
{
    class MovementManager
    {
        public static Composite CreateMoveToLosBehavior()
        {
            return CreateMoveToLosBehavior(ret => StyxWoW.Me.CurrentTarget);
        }

        public static Composite StopRangeBehaviour()
        {
            return new Decorator(
                ret => StyxWoW.Me.CurrentTarget.Distance < 15,
                new Sequence(
                    new Action(ret =>
                                    {
                                        CreateEnsureMovementStoppedBehavior();
                                    })
                    )
                );
        }

        public static Composite CreateEnsureMovementStoppedBehavior()
        {
            return new Decorator(
                ret => StyxWoW.Me.IsMoving,
                new Sequence(
                    new Action(ret => Navigator.PlayerMover.MoveStop()),
                    new Action(ret =>
                                   {
                                       if (_lastguidMoveStop == StyxWoW.Me.CurrentTarget.Guid)
                                           return;
                                       _lastguidMoveStop = StyxWoW.Me.CurrentTarget.Guid;
                                       Logger.MovementLog(string.Format("MoveStop: to close to {0} GUID:{1}",
                                                                        StyxWoW.Me.CurrentTarget.Name,
                                                                        _lastguidMoveStop));
                                   }))
                );
        }

        public static Composite MaxRangeBehaviour()
        {
            return MaxRangeBehaviour(ret => StyxWoW.Me.CurrentTarget);
        }

        private static Composite MaxRangeBehaviour(UnitSelectionDelegate target)
        {
         
            return new Decorator(
                 ret => StyxWoW.Me.CurrentTarget.Distance > 30 && !StyxWoW.Me.IsCasting,
                 new Sequence(
                     new Action(ret =>
                                     {
                                         StyxWoW.Me.CurrentTarget.Face();
                                         Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                                         if (_lastguidFace == StyxWoW.Me.CurrentTarget.Guid)
                                             return;
                                         _lastguidFace = StyxWoW.Me.CurrentTarget.Guid;
                                         Logger.MovementLog(string.Format("Face and Move: {0} GUID:{1}",
                                                                          StyxWoW.Me.CurrentTarget.Name,
                                                                          _lastguidFace));
                                     })
                 )
             );
        }

        public static Composite StopRightHereBehaviour()
        {
            return new Decorator(
                ret => StyxWoW.Me.IsMoving,
                new Sequence(
                    new Action(ret =>
                    {
                        CreateEnsureMovementStoppedBehavior();
                    })
                    )
                   );
        }

        public static Composite CreateFaceTargetBehavior()
        {
            return CreateFaceTargetBehavior(ret => StyxWoW.Me.CurrentTarget);
        }
        public static Composite CreateFaceTargetBehavior(UnitSelectionDelegate toUnit)
        {
            return new Decorator(
                ret =>
                toUnit != null && toUnit(ret) != null &&
                !StyxWoW.Me.IsMoving && !toUnit(ret).IsMe &&
                !StyxWoW.Me.IsSafelyFacing(toUnit(ret), 45),
                new Sequence(
                    new Action(ret =>
                                   {
                                       StyxWoW.Me.CurrentTarget.Face();
                                       if (_lastguidFace == StyxWoW.Me.CurrentTarget.Guid)
                                           return;
                                       _lastguidFace = StyxWoW.Me.CurrentTarget.Guid;
                                       Logger.MovementLog(string.Format("Face: {0} GUID:{1}",
                                                                        StyxWoW.Me.CurrentTarget.Name,
                                                                        _lastguidFace));
                                   })
                    )
                );
        }

        public static Composite CreateMoveToTargetBehavior(bool stopInRange, DynamicRangeRetriever range)
        {
            return CreateMoveToTargetBehavior(stopInRange, range, ret => StyxWoW.Me.CurrentTarget);
        }

        private static Composite CreateMoveToTargetBehavior(bool stopInRange, DynamicRangeRetriever range,
                                                            UnitSelectionDelegate onUnit)
        {
            return
                new Decorator(
                    ret => onUnit != null && onUnit(ret) != null && onUnit(ret) != StyxWoW.Me && !StyxWoW.Me.IsCasting,
                    CreateMoveToLocationBehavior(ret => onUnit(ret).Location, stopInRange, range));
        }

        private static Composite CreateMoveToLosBehavior(UnitSelectionDelegate toUnit)
        {
            return new Decorator(
                ret =>
                toUnit(ret) != null &&
                toUnit(ret) != StyxWoW.Me && (!toUnit(ret).InLineOfSpellSight),
                new Sequence(
                    new Action(ret => Navigator.MoveTo(toUnit(ret).Location)),
                    new Action(ret =>
                                   {
                                       if (_lastguidLos == StyxWoW.Me.CurrentTarget.Guid)
                                           return;
                                       _lastguidLos = StyxWoW.Me.CurrentTarget.Guid;
                                       Logger.MovementLog(string.Format("MovetoLos: {0} GUID:{1}",
                                                                        StyxWoW.Me.CurrentTarget.Name,
                                                                        _lastguidLos));
                                   })
                    )
                );
        }

        #region Root Move To Location
        private static ulong _lastguidMoveto;
        private static ulong _lastguidMoveStop;
        private static ulong _lastguidFace;
        private static ulong _lastguidLos;

        private static Composite CreateMoveToLocationBehavior(LocationRetriverDelegate location, bool stopInRange,
                                                              DynamicRangeRetriever range)
        {
            return
                new Decorator(
                    ret => true,
                    new PrioritySelector(
                        new Decorator(
                            ret => stopInRange && StyxWoW.Me.Location.Distance(location(ret)) < range(ret),
                            new PrioritySelector(
                                CreateEnsureMovementStoppedBehavior(),
                                new Action(ret => RunStatus.Success)
                                )
                            ),
                        new Action(ret =>
                                       {
                                           Navigator.MoveTo(location(ret));
                                           if (_lastguidMoveto == StyxWoW.Me.CurrentTarget.Guid)
                                               return;
                                           _lastguidMoveto = StyxWoW.Me.CurrentTarget.Guid;
                                           Logger.MovementLog(string.Format("MovingTo: {0} GUID:{1}",
                                                                            StyxWoW.Me.CurrentTarget.Name,
                                                                            _lastguidMoveto));
                                       })
                        ));
        }
        #endregion
    }
}